package com.lyon.demo.rpc.naming.dispatcher;

import com.lyon.demo.rpc.api.core.Command;
import com.lyon.demo.rpc.api.core.Types;
import com.lyon.demo.rpc.naming.dispatcher.handler.*;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author LeeYan9
 * @since 2022-04-15
 */
@Slf4j
@ChannelHandler.Sharable
public class DispatcherHandler extends ChannelHandlerAdapter implements ProcessHandlerRegister {

    public static final Map<Integer, ProcessHandler> processHandlers = new ConcurrentHashMap<>();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
       Command command = (Command) msg;
        //todo
        final int type = command.getHeader().getType();
        ProcessHandler processHandler = processHandlers.get(type);
        if (Objects.nonNull(processHandler)) {
            Command response = processHandler.execute(command);
            // Serializer response;
            ctx.channel().writeAndFlush(response);
        } else {
            log.error("找不到对应的处理器{}",type);
            // ...
        }
    }

    @Override
    public void addProcess(int type, ProcessHandler processHandler) {
        processHandlers.put(type, processHandler);
    }

    @Override
    public ProcessHandler getProcess(int type) {
        return processHandlers.get(type);
    }

    public static DispatcherHandler instance(){
        DispatcherHandler dispatcherHandler = new DispatcherHandler();
        dispatcherHandler.addProcess(Types.NamingTypes.register,new ServiceRegisterHandler());
        dispatcherHandler.addProcess(Types.NamingTypes.beat,new ServiceBeatHandler());
        dispatcherHandler.addProcess(Types.NamingTypes.lookup_service_name,new LookupServiceNameHandler());
        dispatcherHandler.addProcess(Types.NamingTypes.lookup_interface,new LookupInterfaceNameHandler());
        dispatcherHandler.addProcess(Types.NamingTypes.register_interface,new InterfaceRegisterHandler());
        return dispatcherHandler;
    }

}
